
#ifndef _TTG_SERVICES_SCHEDULINGALGORITHM_GREED_
#define _TTG_SERVICES_SCHEDULINGALGORITHM_GREED_
#include "Common/Definitions.h"

#include "Runtime.Low/Devices.h"
#include "Runtime.Low/Threads.h"
#include "SchedulingAlgorithm.h"
#include "../Timer/Timer.h"
#include <set>
#include <queue>

namespace ttg_internal
{
	namespace services
	{
		//Auxiliaury class for task comparision.
		struct WiseTaskComparator
		{
			bool operator() (ttg::services::WiseTask *a1, ttg::services::WiseTask *a2) const
			{
				if (a1->getExpectedTime() < a2->getExpectedTime())
					return true;
				if (a1->getExpectedTime() > a2->getExpectedTime())
					return false;
				return a1 < a2;
			}
		};
		class SchedulingAlgorithm_Greed :public SchedulingAlgorithm
		{
			private:
				typedef std::set<ttg::services::WiseTask *, WiseTaskComparator> wise_tasks_set;
				std::queue<ttg::threads::Task *> tasks;
				ttg::devices::DeviceMap<wise_tasks_set> wise_tasks;
				DeviceState *cpu_state;
				ttg::devices::DeviceMap<DeviceState *> device_states;
				std::vector<ttg::devices::DeviceID> device_priorities;
			private:
				//Returns IDs of devices, sorted by priority.
				static std::vector<ttg::devices::DeviceID> createDevicePriorities(
					const std::vector<DeviceState *> &devices);
				//Tries to find suitable combination of this device and API.
				//In case of fail throws ttg::Error().
				ttg::devices::LogicalDevice findSuitableApi(ttg::services::WiseTask *t,
															ttg::devices::DeviceID device);
			public:
				void onPerformedTask(ttg::services::WiseTask *message);
				//Creates empty algorithm.
				SchedulingAlgorithm_Greed(const std::vector<DeviceState *> &devices);
				//SchedulingAlgorithm member.
				virtual void split(std::vector<ttg::services::WiseTask *> &tasks,
								   std::vector<ttg::services::WiseTask *> &root_tasks,
								   std::vector<ttg::services::WiseTask *> &child_tasks);
				//SchedulingAlgorithm member.
				virtual void addTasks(ttg::structures::Enumerator<ttg::threads::Task *> &en);
				//SchedulingAlgorithm member.
				virtual void addTasks(ttg::structures::Enumerator<ttg::services::WiseTask *> &en);
				//SchedulingAlgorithm member.
				virtual ttg::threads::Task *getTask();
		};
	}
}

#endif
